﻿using System;
using System.Reflection;

namespace CobraCms.Core.Content
{
    public class TypedContentMapper<T> where T: class, new()
    {
        public void ToType(ContentNode nodeData, T instance)
        {
            if (nodeData == null)
                return;

            if (nodeData.PropertyData == null)
                return;

            ContentNodeProperty propertyData;
            foreach (var propertyInfo in typeof(T).GetProperties())
            {
                var name = propertyInfo.Name;

                if (!nodeData.PropertyData.TryGetValue(name,out propertyData))
                {
                    continue;
                }
                var propertyType = propertyInfo.PropertyType;

                if (!propertyInfo.CanWrite)
                {
                    continue;
                }
                object value = null;

                if (propertyType == typeof(int))
                {                    
                    propertyInfo.SetValue(instance, propertyData.ValueAsInt32, null);
                }
                else if (propertyType == typeof(long))
                {
                    propertyInfo.SetValue(instance, propertyData.ValueAsInt64, null);
                }
                else if (propertyType == typeof(decimal))
                {
                    propertyInfo.SetValue(instance, propertyData.ValueAsDecimal, null);
                }
                else if (propertyType == typeof(DateTime))
                {                    
                    propertyInfo.SetValue(instance, propertyData.ValueAsDateTime, null);
                }
                else if (propertyType == typeof(string))
                {
                    propertyInfo.SetValue(instance, propertyData.ValueAsString, null);
                }
            }             
        }

        public void FromType(T typedData, ContentNode target)
        {
            if (typedData == null)
                return;

            if (target == null)
                return;

            foreach (var propertyInfo in typeof (T).GetProperties())
            {
                var name = propertyInfo.Name;

                ContentNodeProperty propertyDataItem = null;
                if (!target.PropertyData.TryGetValue(name, out propertyDataItem))
                {
                    propertyDataItem = new ContentNodeProperty();
                    propertyDataItem.PropertyName = propertyInfo.Name;
                    target.PropertyData.Add(propertyDataItem.PropertyName, propertyDataItem);                    
                }
                var propertyType = propertyInfo.PropertyType;

                if (!propertyInfo.CanRead)
                {
                    continue;
                }                

                if (propertyType == typeof (int))
                {
                    propertyDataItem.ValueAsInt32 = (int)propertyInfo.GetValue(typedData, null);
                }
                else if (propertyType == typeof (long))
                {
                    propertyDataItem.ValueAsInt64 = (long)propertyInfo.GetValue(typedData, null);
                }
                else if (propertyType == typeof (decimal))
                {
                    propertyDataItem.ValueAsDecimal = (Decimal)propertyInfo.GetValue(typedData, null);
                }
                else if (propertyType == typeof (DateTime))
                {
                    propertyDataItem.ValueAsDateTime = (DateTime)propertyInfo.GetValue(typedData, null);
                }
                else if (propertyType == typeof (string))
                {
                    propertyDataItem.ValueAsString = propertyInfo.GetValue(typedData, null) as string; 
                }
            }
        }
    }
}
